package org.example.spring_frist.learn;

import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;


/**
 * 当启动了这个spring框架，会启动所有的类，
 * 每次在访问指定的方法时都会在框架中查找指定的方法
 * 但是如果是要遍历整个框架的话，那显然是不现实的效率太低下了，
 * 这时就使用RestController要查找的方法再这个类中，这样就缩小了范围
 * 但是这样仍然要查找类中的所有方法，这样仍然是不科学的，这时就可以使用RequestMapping
 * 来与方法建立起一一映射的关系，这样是查找效率更加高效
 * 且RequestMapping映射的key是唯一的
 */
@RestController//如果没有这个标签的话是spring扫描时不会扫描这个类，那么在匹配这个类中的方法的话就是失败404
@RequestMapping("/hello")
public class hello {

    //这个用来标识额度是hello1这个方法，切对于发起的请求是post或者是get都支持
    @RequestMapping("/hello1")//路径映射
    public String hello1() {
        return "Hello World";
    }

    //单独设置只能接收post的请求
    @RequestMapping(value = "/hello2", method = RequestMethod.POST)
    public String hello2(String name) {
        return "Hello World2";
    }

    //单独设置只能接收get的请求
    @RequestMapping(value = "/hello3", method = RequestMethod.GET)
    public String hello3(String name) {
        return "Hello World3";
    }

    //只能接受post请求
    @PostMapping("/postM1")
    public String postM() {
        return "Hello postM";
    }

    //只能接受get请求
    @GetMapping("/getM2")
    public String GetM() {
        return "Hello getM";
    }

    //对于数组的接受
    @GetMapping("/arr")
    public String GetArr(int[] arr) {
        return Arrays.toString(arr);
    }

    @GetMapping("/String")
    public String GetString(String[] strings) {
        return Arrays.toString(strings);
    }

    //从前端接收数据到q，并赋值给value 这式url在在传值是赋给q，然后后端在赋值给自己定义的变量value
    @RequestMapping("/All")
    public String GetAll(@RequestParam(value = "q") String value) {
        return value;
    }

    //传递集合 和数组一样的传参
    @RequestMapping("list")
    public String list(@RequestParam List<Integer> list) {
        return Arrays.toString(list.toArray());
    }

    //多个参数的传递
    @RequestMapping("more")
    public String more(String s1, Integer i2) {
        return s1 + " " + i2;
    }

    /**
     * json是一种语法格式实际就是一串字符串，他在前后端数据交互中广泛使用，可以被多种编程语言解析和生成
     * 在前后端交互中可以使用多种格式，而json在这些的地位就相当于是英语在全球的地位，
     * 前端在传递数据时使用的url中就可以包含json，而后端也可以放回json给前端，再使用时在翻译下就行
     * 类和json之间可以相互装换的 接收json需要@RequestBody这个标签
     */
    //json的传递使用 使用@RequestBody标签标记 只要是提供了一个get或者set方法都可以正常接收值
    @RequestMapping("json")
    public String json(@RequestBody hello2.classInfo info) {
        return info.toString();
    }

    //获取url中的参数 使用@PathVariable这个标签大括号里面的参数就死我要得到的元素
    @RequestMapping("/value/{name}")
    public String value(@PathVariable String name) {
        return "name = " + name;
    }

    @RequestMapping("/values/{name}/{age}")
    public String values(@PathVariable("age") Integer integer, @PathVariable("name") String name) {
        return "name = " + name + " age = " + integer;
    }


    //接受文件
    @RequestMapping("/file")
    public String file(@RequestPart MultipartFile file) {
        //获取文件的名字
        String s = file.getOriginalFilename();
        try {
            //将文件上传到指定路径 放到new的File这个文件中 如果指定的是一个文件夹是不行的
            //因为这个方法是将接收到的文件的内容传输到指定的文件中的
            file.transferTo(new File("C:\\Users\\15328\\OneDrive\\桌面/hh.txt"));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return s;
    }

    @RequestMapping("/target")
    public Object target(@RequestBody hello2.classInfo info) {
        System.out.println(info.toString());
        return info;
    }

    /**
     * Cookie 和 Session
     * http是无状态的协议他不会记录上一次通信，但在有些情况下需要知道上一次的通信，比如再次登录同一个网站的时候
     * 不会让你重复的输入密码，这就是因为服务器知道了上次一次通信
     * Session是服务去为这段通信单独生成的一个类对象，保存在服务器中并会生成以个唯一的SessionId来找到这个类对象
     * 在服务器把响应放回给客户端时，SessionId也会被传过去，这是客户端再把这个SessionId保存在Cookie中
     * 在下一次客户端再次访问同一个界面时，会把SessionId也传过去，这样服务器就能知道上一次的通信信息，在返回对应的响应
     * 区别
     * Cookie是客户端储存对话信息的方式，Session是服务器储存信息的方式
     * Cookie和Session通过主要SessionId联系，SessionId是他们之间的桥梁
     * Cookie和Session通常一起使用，但也不是必须搭配使用
     * 1. Cookie也可以储存其他的信息，不一定都是SessionId
     * 2. SessionId也不一定都是通过Cookie或者Set—Cookie来传递，也可以跟着url一起传递
     * --
     * * 服务器通过JSESSIONID来获取对应色Session对象，在通过对于的name字段来获取储存在Session中的值 *
     */

    /**
     * HttpServletRequest 和 HttpServletResponse
     * Spring MVC 是基于Servlet API构建的web框架
     * 而HttpServletResponse和HttpServletRequest是Servlet中的俩个类，而Spring就对着俩个对象进行了封装
     * HttpServletRequest记录的是客户端通过http发起请求的所有信息、
     * HttpServletResponse记录的是服务器向客户端返回的响应的所有信息
     * 服务器期望从客户端中获得什么，都可以从HttpServletRequest中获得
     * 客户端想从服务器中获得什么，都可以从HttpServletRequest中获得
     */
    //获取Cookie
    @RequestMapping("/r1")
    public String r1(HttpServletRequest request) {
        //获取所有的cookie cookie是一个类
        Cookie[] cookie = request.getCookies();
        StringBuilder s = new StringBuilder();
        for (Cookie c : cookie) {
            s.append(c.getName() + " " + c.getValue() + "\n");
        }
        System.out.println(s);
        return "cookie " + s.toString();
    }

    //设置cookie
    @RequestMapping("setCookie")
    public void setCookie(HttpServletResponse response) {
        Cookie cookie = new Cookie("name", "value");
        response.addCookie(cookie);
    }

    //直接获取对应的值
    @RequestMapping("r2")
    public String r2(@CookieValue("hhh") String cookieValue) {
        return cookieValue;
    }

    //获取Session 硬卧Session是储存在服务器上的，所以子啊获取时要先储存session
    @RequestMapping("/set")
    public String set(HttpServletRequest request) {
        HttpSession session = request.getSession();
        //参数设置为false 并且没有cookie 我刚去掉了 此时session是null
        //参数设置为true 并且没有cookie 我刚去掉了 此时session不是null 是个对象
        //参数不设置 并且没有cookie 我刚去掉了 此时session不是null 是个对象 说明这里参数默认是true 和参数设置为true是保持一致的
        if (session != null) {
            session.setAttribute("hhh", 666);
            return "success";
        }
        return "no success";
    }

    @RequestMapping("/r3")
    public String r3(HttpServletRequest request) {
        HttpSession session = request.getSession();
        if (session != null && session.getAttribute("hhh") != null) {
            return session.getAttribute("hhh").toString();
        }
        return "false";
    }

    @RequestMapping("/r4")
    public String r4(@SessionAttribute(value = "hhh", required = false) String hhh) {
        return hhh;
    }

    @RequestMapping("/r5")
    public String r5(HttpSession request) {
        String h = (String) request.getAttribute("hhh");
        return h;
    }

    //获取header getHeader中加上指定的字段就好
    @RequestMapping("/r6")
    public String r6(HttpServletRequest request) {
        String h = request.getHeader("User-Agent");
        return h;
    }

    //HttpServletResponse 这个类是spring自己创建的，参数这样写就是调用spring自己实例化的对象
    //而这个对象最后会作为响应返回给客户端
    @RequestMapping("/r7")
    public void r7(HttpServletResponse response) {
        response.setStatus(444);//设置返回的状态码
    }


}










